package ${projectDomain}.service.imports.system;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import ${projectDomain}.adapter.logger.LoggerImportTaskAdapter;
import ${projectDomain}.adapter.system.SystemDepartmentAdapter;
import ${projectDomain}.adapter.validate.IValidateAdapter;
import ${projectDomain}.enums.OperatorTypeEnum;
import ${projectDomain}.enums.imports.task.ImportTaskEventEnum;
import ${projectDomain}.imports.IImportBusinessService;
import ${projectDomain}.pojo.bo.system.department.SystemDepartmentImportBo;
import ${projectDomain}.pojo.bo.system.department.SystemDepartmentImportStopBo;
import ${projectDomain}.pojo.dao.logger.imports.task.LoggerImportTaskInsertDo;
import ${projectDomain}.pojo.dao.system.department.SystemDepartmentDataDo;
import ${projectDomain}.pojo.dao.system.department.SystemDepartmentInsertDo;
import ${projectDomain}.pojo.mo.system.department.SystemDepartmentImportMo;
import ${projectDomain}.pojo.mso.logger.imports.task.LoggerImportTaskQueueMso;
import ${projectDomain}.pojo.vo.system.department.SystemDepartmentImportStopVo;
import ${projectDomain}.pojo.vo.system.department.SystemDepartmentImportVo;
import ${projectDomain}.rabbit.RabbitConstant;
import ${projectDomain}.rabbit.RabbitQueue;
import ${projectDomain}.service.BaseService;
import ${projectDomain}.service.LoggerService;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.JsonUtils;
import com.unswift.utils.ObjectUtils;

@Service
@Api(value="部门导入服务", author="liyunlong", date="2024-01-11", version="1.0.0")
public class SystemDepartmentImportService extends BaseService implements IImportBusinessService<SystemDepartmentImportMo, SystemDepartmentImportBo>, RabbitConstant{
	
	@Autowired
	@ApiField("部门公共服务")
	private SystemDepartmentAdapter systemDepartmentAdapter;
	
	@Autowired
	@ApiField("导出任务服务")
	private LoggerImportTaskAdapter loggerImportTaskAdapter;
	
	@Autowired
	@ApiField("操作日志服务")
	private LoggerService loggerService;
	
	@Autowired
	@ApiField("Rabbit Mq发送消息服务")
	private RabbitQueue rabbitQueue;
	
	@Autowired
	@ApiField("表单验证公共操作")
	private IValidateAdapter validateAdapter;
	
	@ApiMethod(value="导入会员(不要加事务，否则有可能导致任务还没创建，但是队列已经消费查询，最终导致导入报错)", params=@ApiField("导入业务实体，包含附件信息"), returns=@ApiField("导入结果Vo->result:{0：未被导入，1：已成功导入}"))
	public SystemDepartmentImportVo imports(SystemDepartmentImportBo importBo) {
		ExceptionUtils.trueException(loggerImportTaskAdapter.existsTasking(this.getUserId(), systemDepartmentAdapter.getModule()), "task.is.currently.executing", "有部门导入");
		Date date=new Date();
		LoggerImportTaskInsertDo task=new LoggerImportTaskInsertDo();
		task.setName("部门");
		task.setModule(systemDepartmentAdapter.getModule());
		task.setDocumentType("excel");
		task.setStatus((byte)0);
		task.setStartTime(date);
		task.setImportBeanClass(this.getClass().getName());
		task.setImportModelClass(SystemDepartmentImportBo.class.getName());
		task.setImportData(JsonUtils.toJson(importBo));
		task.setResult((byte)0);
		int result=loggerImportTaskAdapter.save(task, false);//保存任务，不用加事务，防止队列消费的时候还没保存完数据
		rabbitQueue.sendMessage(IMPORT_EXCHANGE_NAME, IMPORT_ROUTE_KEY, new LoggerImportTaskQueueMso(task.getId(), ImportTaskEventEnum.START, this.getHeader(tokenConfig.getKeyName()), getLanguage()));//发送导出队列
		return new SystemDepartmentImportVo(task.getId(), result);
	}
	
	@ApiMethod(value="停止导出部门", params=@ApiField("停止导出对象"))
	public SystemDepartmentImportStopVo stop(SystemDepartmentImportStopBo importStopBo){
		rabbitQueue.sendMessage(IMPORT_STOP_EXCHANGE_NAME, IMPORT_STOP_ROUTE_KEY, new LoggerImportTaskQueueMso(importStopBo.getId(), ImportTaskEventEnum.STOP, this.getHeader(tokenConfig.getKeyName()), getLanguage()));//发送停止导出队列
		return new SystemDepartmentImportStopVo(1);
	}
	
	@Override
	@ApiMethod(value="获取导出模板的类类型", returns=@ApiField("导出模板类类型"))
	public Class<SystemDepartmentImportMo> getModule(){
		return SystemDepartmentImportMo.class;
	}
	
	@Override
	@ApiMethod(value="导入行数据验证，请再此处处理完所有的验证，否则可能导致数据导入一部分", params = {@ApiField("需验证的行数据"), @ApiField("此数据在excel中的行次（从零开始）"), @ApiField("操作导出的用户token"), @ApiField("导入条件")})
	public void validate(SystemDepartmentImportMo rowData, int rowIndex, String token, SystemDepartmentImportBo condition) {
		rowData.setRowNumber(rowIndex+1);
		rowData.setParentNamePathExistsExcel(false);
		String departmentPath=ObjectUtils.isEmpty(rowData.getParentNamePath())?rowData.getName():rowData.getParentNamePath()+"/"+rowData.getName();
		String departmentPathKey=getUserToken(token)+"-DepartmentPath";
		if(!memoryCache.existsHash(departmentPathKey, departmentPath)) {
			memoryCache.setHash(departmentPathKey, departmentPath, true);
		}
		if(ObjectUtils.isNotEmpty(rowData.getParentNamePath())) {
			if(memoryCache.existsHash(departmentPathKey, rowData.getParentNamePath())) {
				rowData.setParentNamePathExistsExcel(true);
			}
		}
		validateAdapter.validate(systemDepartmentAdapter.getModule(), "import", rowData, this.getUser(token), systemDepartmentAdapter);//验证表单
	}
	
	@Override
	@Transactional("systemTransactionManager")
	@ApiMethod(value="导入数据批量处理，批次数据根据nocos配置确定批次大小", params = {@ApiField("批次数据"), @ApiField("此列表在excel中的开始行次（从零开始）"), @ApiField("操作导出的用户token"), @ApiField("导入条件")})
	public void handleBatch(List<SystemDepartmentImportMo> rowList, int startRowIndex, String token, SystemDepartmentImportBo condition) {
		Long userId=this.getUserId(token);
		List<SystemDepartmentInsertDo> batchList=this.convertPojoList(rowList, SystemDepartmentInsertDo.class);
		int sort;
		Map<Long, Integer> sortMap=new HashMap<Long, Integer>();
		for (SystemDepartmentInsertDo insert : batchList) {
			insert.setType(cacheAdapter.findDictionaryKeyByValue("departmentType", insert.getType()));
			if(ObjectUtils.isEmpty(insert.getParentNamePath())) {
				if(!sortMap.containsKey(-1L)) {
					sort=systemDepartmentAdapter.findMaxSort(null);
					sortMap.put(-1L, sort);
				}
				insert.setSort(sortMap.get(-1L));
				sortMap.put(-1L, sortMap.get(-1L)+1);
			}else {
				SystemDepartmentDataDo parent = systemDepartmentAdapter.findByNamePath(insert.getParentNamePath());
				if(!sortMap.containsKey(parent.getId())) {
					sort=systemDepartmentAdapter.findMaxSort(parent.getId());
					sortMap.put(parent.getId(), sort);
				}
				insert.setParentId(parent.getId());
				insert.setParentPath(ObjectUtils.isEmpty(parent.getParentPath())?"."+parent.getId()+".":parent.getParentPath()+parent.getId()+".");
				insert.setSort(sortMap.get(parent.getId()));
				sortMap.put(parent.getId(), sortMap.get(parent.getId())+1);
			}
			insert.setCreateUser(userId);
			insert.setChangeUser(userId);
			systemDepartmentAdapter.save(insert, false);//数据插入改为逐个插入，保证：systemDepartmentAdapter.findByNamePath时都能取到值
		}
		int index=0;
		for (SystemDepartmentImportMo importData : rowList) {
			long id=batchList.get(index).getId();
			loggerService.writer(id, systemDepartmentAdapter.getModule(), OperatorTypeEnum.IMPORT, token, importData);//记录日志
			index++;
		}
	}
	
	@Override
	@ApiMethod(value="结束导入时触发，如清理临时缓存等", params = {@ApiField("用户token")})
	public void finish(String token) {
		String departmentPathKey=getUserToken(token)+"-DepartmentPath";
		memoryCache.remove(departmentPathKey);
		validateAdapter.finish();
	}
}